package view;

import controller.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import util.Arithmetic;
import util.Images;
import util.PaintUtilities;
import view.tool.ToolType;

public class GUI extends JFrame {

	public static final String TITLE = "Music Sequencer";

	private EditorPanel editorPanel;
	private MenuPanel menuPanel;
	private ToolPanel toolPanel;

	private JSplitPane splitPane;

	public GUI() {
		super(TITLE);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setIconImage(Images.getApplicationIcon());
		this.addComponentListener(new WindowController()); //Controls this window's size.

		JPanel mainPanel = new JPanel();
		mainPanel.setBackground(new Color(0x333333));
		mainPanel.setPreferredSize(WindowController.MIN_SIZE);
		mainPanel.setLayout(new BorderLayout());

		editorPanel = new EditorPanel(this);
		menuPanel = new MenuPanel();
		toolPanel = new ToolPanel();

		splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true,
			editorPanel, toolPanel
		);
		splitPane.setResizeWeight(0.8);
		splitPane.setOneTouchExpandable(true);
		splitPane.setOpaque(false);
		splitPane.setBorder(null);

		mainPanel.add(menuPanel, BorderLayout.NORTH);
		mainPanel.add(splitPane, BorderLayout.CENTER);

		//Change tools when these buttons are pressed.
		ToolChangeListener tcl = new ToolChangeListener();
		menuPanel.getEffectsButton().addItemListener(tcl);
		menuPanel.getOptionsButton().addItemListener(tcl);
		menuPanel.getEffectsButton().addActionListener(tcl);
		menuPanel.getOptionsButton().addActionListener(tcl);

		this.setContentPane(mainPanel);

		this.pack();
		this.setLocationRelativeTo(null);

		Insets insets = this.getInsets();

		this.setMinimumSize(Arithmetic.addInsets(new Dimension(320, 240), insets));
		this.showToolPanel(ToolType.OPTIONS); //Show File dialogue at startup
	}

	/*
	 * Set the ToolPanel to show the specified ToolType and pop it out
	 * automatically if it's hidden.
	 */
	public void showToolPanel(ToolType type) {
		setToolPanel(type);
		splitPane.resetToPreferredSizes();
	}

	/*
	 * Set the ToolPanel to show the specified ToolType. Unlike showToolPanel, this
	 * method will not pop it out automatically if it's hidden.
	 */
	public void setToolPanel(ToolType type) {
		if(type != ToolType.EFFECTS) menuPanel.getEffectsButton().setSelected(false);
		else menuPanel.getEffectsButton().setSelected(true);

		if(type != ToolType.OPTIONS) menuPanel.getOptionsButton().setSelected(false);
		else menuPanel.getOptionsButton().setSelected(true);

		toolPanel.setTool(type);
	}

	/**
	 * Closes the ToolPanel.
	 */
	public void collapseToolPanel() {
		splitPane.setDividerLocation(1f);
	}

	/**
	 * Resets the ToolPanel to the EFFECTS tool and collapses it.
	 */
	public void resetToolPanel() {
		toolPanel.setTool(ToolType.EFFECTS);
		collapseToolPanel();
	}

	public MenuPanel getMenuPanel() {
		return menuPanel;
	}

	public EditorPanel getEditorPanel() {
		return editorPanel;
	}

	public ToolPanel getToolPanel() {
		return toolPanel;
	}

	/**
	 * Change the name shown in the MenuPanel as well as on the title of this frame.
	 */
	public void changePieceName(String name) {
		this.setTitle(TITLE + " - " + name);
		menuPanel.setPieceName(name);
	}

	public void setChangePieceListener(ChangePieceListener cpl) {
		toolPanel.getOptionsTool().setChangePieceListener(cpl);
		toolPanel.getEffectsTool().setChangePieceListener(cpl);
	}

	public void setPlayerControlListener(PlayerControlListener pcl) {
		menuPanel.setPlayerControlListener(pcl);
		editorPanel.setPlayerControlListener(pcl);
	}

	public void setAddSequenceListener(AddSequenceListener asl) {
		editorPanel.setAddSequenceListener(asl);
	}

	public void setNameChangeListener(NameChangeListener ncl) {
		menuPanel.setNameChangeListener(ncl);
	}

	public void setTempoChangeListener(TempoChangeListener tcl) {
		toolPanel.getEffectsTool().setTempoChangeListener(tcl);
	}

	@Override
	public void paint(Graphics g) {
		//Make painting smooth and pretty.
		Graphics2D g2 = (Graphics2D)g;
		PaintUtilities.setUpGraphics(g2);

		super.paint(g2);
	}

	/**
	 * Listens for events requesting the tool shown to change.
	 */
	public class ToolChangeListener implements ItemListener, ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			Object obj = e.getSource();
			if(obj instanceof JToggleButton) {
				JToggleButton button = ((JToggleButton)obj);
				if(!button.isSelected()) {
					//Button unselected, close the tool panel.
					collapseToolPanel();
				}
			}
		}

		@Override
		public void itemStateChanged(ItemEvent e) {
			ItemSelectable item = e.getItemSelectable();
			if(item instanceof JToggleButton) {
				if(e.getStateChange() == ItemEvent.SELECTED) {
					//Show the tool panel associated with this button.
					String command = ((JToggleButton)item).getActionCommand();
					showToolPanel(ToolType.valueOf(command));
				}
			}
		}
	}
}
